/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.swosh.stomp.ejb;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * Implementace PersonDAO. Má za ukol CRUD operace s Person entitami.
 * @author swosh
 */
@Stateless(name = "PersonDAO")
@Remote(PersonDAORemote.class)
@Local(PersonDAO.class)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class PersonDAOBean implements PersonDAO, PersonDAORemote {

    private static final Logger log = Logger.getLogger(PersonDAOBean.class.getSimpleName());
    @PersistenceContext(unitName = "stomp")
    private EntityManager em;

    /**
     * Uloží osobu do db.
     * @param p
     */
    @Override
    public void addPerson(Person p) {
        try {
            em.persist(p);
            em.flush();
            em.refresh(p);
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());

        }
    }

    @Override
    public List<Person> getPersons() {
        List<Person> pl = new ArrayList<Person>();
        try {
            Query q = em.createNativeQuery("SELECT id, lon, municipalty,"
                    + " description, numori, name,"
                    + " street, image, lat  FROM Person p ");
            List rl = q.getResultList();
            for (Iterator it = rl.iterator(); it.hasNext();) {
                Object[] object = (Object[]) it.next();
                Person p = new Person();
                p.setId((Integer) object[0]);
                p.setLon((Double) object[1]);
                p.setMunicipalty((String) object[2]);
                p.setDescription((String) object[3]);
                p.setNumOri((Integer) object[4]);
                p.setName((String) object[5]);
                p.setStreet((String) object[6]);
                p.setImage((byte[]) object[7]);
                p.setLat((Double) object[8]);


                pl.add(p);

            }

            return pl;
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());
            return pl;
        }
    }

    @Override
    public void updatePerson(int pk, Person newP) {
        try {
            Person oldP = em.find(Person.class, pk);
            if (newP.getDescription() != null) {
                oldP.setDescription(newP.getDescription());
            }
            if (newP.getImage() != null) {
                oldP.setImage(newP.getImage());
            }
            oldP.setLat(newP.getLat());
            oldP.setLon(newP.getLon());
            if (newP.getMunicipalty() != null) {
                oldP.setMunicipalty(newP.getMunicipalty());
            }
            if (newP.getName() != null) {
                oldP.setName(newP.getName());
            }
            if (newP.getStreet() != null) {
                oldP.setStreet(newP.getStreet());
            }
            oldP.setNumOri(newP.getNumOri());

            em.merge(oldP);
            em.flush();
            em.refresh(oldP);
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());
        }
    }

    /**
     * Původně pro derby byl tvar
     *
     * Query q = em.createNativeQuery("SELECT id, name, lat, lon FROM Person p ", Person.class);
    List<Person> rl = q.getResultList();
    return rl;
    Query q = em.createNativeQuery("SELECT id, name, lat, lon FROM Person p ");
    List rl = q.getResultList();
     * U postgre nemůžu použít code stejný jako pro javadb. Objeví se chyba, že pk je null.
     * @return
     */
    @Override
    public List<Person> getPersonsLatLonNameId() {
        List<Person> pl = new ArrayList<Person>();
        try {
            Query q = em.createNativeQuery("SELECT id, name, lat, lon FROM Person p ");
            List rl = q.getResultList();


            for (Iterator it = rl.iterator(); it.hasNext();) {
                Object[] object = (Object[]) it.next();
                Person p = new Person();
                int id = (Integer) object[0];
                p.setId(id);
                p.setName((String) object[1]);
                double lat = (Double) object[2];
                p.setLat(lat);
                double lon = (Double) object[3];
                p.setLon(lon);
                pl.add(p);
            }
            return pl;
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());
            return pl;
        }



    }

    @Override
    public Person getPerson(int id) {
        try {
            Person person = em.find(Person.class, id);
            if (person == null){
                return new Person();
            } else {
                return person;
            }
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());
            return new Person();
        }
    }

    /**
     * Maže Person entity. Velmi bolestivé bylo zjišťování, že nemohu užít
     * jen em.remove(p2). Eclipselink si neuloží pk při vytvoření objektu.
     * Očekával bych, id bude uloženo do pk
     * K pk objektu se dostanu až poté, co ho najdu metodou find.
     * @param p
     */
    @Override
    public void deletePerson(Person p) {
        try {
            Person p2 = em.find(Person.class, p.getId());
            em.remove(p2);
            em.flush();
        } catch (Exception e) {
            log.log(Level.WARNING, e.getMessage());
        }
    }
}
